home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / nasanets.zip / LNRATE.C < prev    next >
C/C++ Source or Header  |  1990-06-07  |  14KB  |  306 lines

  1. /*=============================*/
  2. /*           NETS              */
  3. /*                             */
  4. /* a product of the AI Section */
  5. /* NASA, Johnson Space Center  */
  6. /*                             */
  7. /* principal author:           */
  8. /*       Paul Baffes           */
  9. /*                             */
  10. /* contributing authors:       */
  11. /*      Bryan Dulock           */
  12. /*      Chris Ortiz            */
  13. /*=============================*/
  14.  
  15.  
  16. /*
  17. ----------------------------------------------------------------------
  18.   Code For Cosecant Learning Rate Adjustment (Prefix = LR_)
  19. ----------------------------------------------------------------------
  20.   This code is divided into 4 major sections:
  21.  
  22.   (1) include files
  23.   (2) externed routines
  24.   (3) global variables
  25.   (4) subroutines
  26.  
  27.   Each section is further explained below.
  28. ----------------------------------------------------------------------
  29. */
  30.  
  31.  
  32. /*
  33. ----------------------------------------------------------------------
  34.   INCLUDE FILES
  35. ----------------------------------------------------------------------
  36. */
  37. #include  "common.h"
  38.  
  39.  
  40. /*
  41. ----------------------------------------------------------------------
  42.   EXTERNED ROUTINES
  43. ----------------------------------------------------------------------
  44. */
  45. extern Sint  C_float_to_Sint();
  46.  
  47.  
  48. /*
  49. ======================================================================
  50.   ROUTINES IN LNRATE.C
  51. ======================================================================
  52.   The only routine in this file is one which takes a Sint value which
  53.   represents a sum and returns the semilinear activation value.
  54.  
  55.   Type Returned                 Routine                                 
  56.   -------------                 -------                                 
  57.     float                       LR_learn_default();
  58.     float                       LR_momentum_default();
  59.     float                       LR_scale_default();
  60.     float                       LR_learn_from_scale();
  61.     D_Sint                      LR_calc_learn_rate();
  62. ======================================================================
  63. */
  64.  
  65.  
  66. /*
  67. ----------------------------------------------------------------------
  68.   GLOBAL VARIABLES
  69. ----------------------------------------------------------------------
  70.   The only global variable used by this code is a table needed for storing
  71.   all of the cosecant values between 0 and pi/2. This table is generated
  72.   to help speed things up when learning rates are being calculated. Rather
  73.   than run the rather slow (1/sin(x)) function, a table reference is 
  74.   made which will generate the appropriate answer.  In short, we pre-
  75.   calculate all possible values for the cosecant and store them in a table 
  76.   using the incoming value as a lookup.
  77.   Below are three global variables used in this file. The first two are
  78.   used to offset the cosecant function by scale (ie, make the function
  79.   more or less steep) and by shifting (ie, moving the cosecant function
  80.   up or down the y-axis). Following that is a pre-calculated set of 
  81.   half the cosecant values (the cosecant is symetric so only half are
  82.   needed). Once referenced, these values are multiplied by  LR_SCALE 
  83.   and added to LR_SHIFT to yield the final result. 
  84. ----------------------------------------------------------------------
  85. */       
  86.  
  87. static float  cosec[] = {
  88. 325.950, 162.976, 108.651,  81.489,  65.192,  54.328,  46.568,  40.748,
  89.  36.221,  32.600,  29.637,  27.169,  25.080,  23.289,  21.738,  20.380,
  90.  19.182,  18.118,  17.165,  16.308,  15.532,  14.827,  14.183,  13.594,
  91.  13.051,  12.550,  12.086,  11.655,  11.254,  10.880,  10.530,  10.202,
  92.   9.894,   9.604,   9.331,   9.073,   8.828,   8.597,   8.378,   8.169,
  93.   7.971,   7.782,   7.602,   7.430,   7.266,   7.109,   6.959,   6.815,
  94.   6.677,   6.545,   6.417,   6.295,   6.177,   6.064,   5.955,   5.849,
  95.   5.748,   5.650,   5.555,   5.463,   5.375,   5.289,   5.206,   5.126,
  96.   5.048,   4.973,   4.899,   4.828,   4.759,   4.692,   4.627,   4.564,
  97.   4.503,   4.443,   4.385,   4.328,   4.273,   4.219,   4.167,   4.116,
  98.   4.066,   4.017,   3.970,   3.924,   3.879,   3.834,   3.791,   3.749,
  99.   3.708,   3.668,   3.629,   3.590,   3.553,   3.516,   3.480,   3.445,
  100.   3.410,   3.377,   3.344,   3.311,   3.279,   3.248,   3.218,   3.188,
  101.   3.159,   3.130,   3.102,   3.074,   3.047,   3.020,   2.994,   2.968,
  102.   2.943,   2.918,   2.894,   2.870,   2.847,   2.824,   2.801,   2.779,
  103.   2.757,   2.735,   2.714,   2.693,   2.673,   2.652,   2.633,   2.613,
  104.   2.594,   2.575,   2.556,   2.538,   2.520,   2.502,   2.485,   2.468,
  105.   2.451,   2.434,   2.418,   2.401,   2.385,   2.370,   2.354,   2.339,
  106.   2.324,   2.309,   2.294,   2.280,   2.266,   2.252,   2.238,   2.224,
  107.   2.211,   2.197,   2.184,   2.171,   2.159,   2.146,   2.134,   2.121,
  108.   2.109,   2.097,   2.086,   2.074,   2.062,   2.051,   2.040,   2.029,
  109.   2.018,   2.007,   1.996,   1.986,   1.976,   1.965,   1.955,   1.945,
  110.   1.935,   1.925,   1.916,   1.906,   1.897,   1.887,   1.878,   1.869,
  111.   1.860,   1.851,   1.842,   1.834,   1.825,   1.817,   1.808,   1.800,
  112.   1.792,   1.784,   1.776,   1.768,   1.760,   1.752,   1.744,   1.737,
  113.   1.729,   1.722,   1.714,   1.707,   1.700,   1.693,   1.686,   1.679,
  114.   1.672,   1.665,   1.658,   1.651,   1.645,   1.638,   1.632,   1.625,
  115.   1.619,   1.613,   1.607,   1.600,   1.594,   1.588,   1.582,   1.576,
  116.   1.570,   1.565,   1.559,   1.553,   1.548,   1.542,   1.536,   1.531,
  117.   1.526,   1.520,   1.515,   1.510,   1.504,   1.499,   1.494,   1.489,
  118.   1.484,   1.479,   1.474,   1.469,   1.464,   1.460,   1.455,   1.450,
  119.   1.446,   1.441,   1.436,   1.432,   1.427,   1.423,   1.419,   1.414,
  120.   1.410,   1.406,   1.401,   1.397,   1.393,   1.389,   1.385,   1.381,
  121.   1.377,   1.373,   1.369,   1.365,   1.361,   1.357,   1.353,   1.350,
  122.   1.346,   1.342,   1.339,   1.335,   1.331,   1.328,   1.324,   1.321,
  123.   1.317,   1.314,   1.310,   1.307,   1.304,   1.300,   1.297,   1.294,
  124.   1.290,   1.287,   1.284,   1.281,   1.278,   1.275,   1.272,   1.268,
  125.   1.265,   1.262,   1.259,   1.257,   1.254,   1.251,   1.248,   1.245,
  126.   1.242,   1.239,   1.237,   1.234,   1.231,   1.228,   1.226,   1.223,
  127.   1.220,   1.218,   1.215,   1.213,   1.210,   1.208,   1.205,   1.203,
  128.   1.200,   1.198,   1.195,   1.193,   1.191,   1.188,   1.186,   1.184,
  129.   1.181,   1.179,   1.177,   1.175,   1.172,   1.170,   1.168,   1.166,
  130.   1.164,   1.162,   1.160,   1.157,   1.155,   1.153,   1.151,   1.149,
  131.   1.147,   1.145,   1.143,   1.141,   1.140,   1.138,   1.136,   1.134,
  132.   1.132,   1.130,   1.128,   1.127,   1.125,   1.123,   1.121,   1.120,
  133.   1.118,   1.116,   1.114,   1.113,   1.111,   1.109,   1.108,   1.106,
  134.   1.105,   1.103,   1.101,   1.100,   1.098,   1.097,   1.095,   1.094,
  135.   1.092,   1.091,   1.089,   1.088,   1.087,   1.085,   1.084,   1.082,
  136.   1.081,   1.080,   1.078,   1.077,   1.076,   1.074,   1.073,   1.072,
  137.   1.071,   1.069,   1.068,   1.067,   1.066,   1.064,   1.063,   1.062,
  138.   1.061,   1.060,   1.059,   1.058,   1.056,   1.055,   1.054,   1.053,
  139.   1.052,   1.051,   1.050,   1.049,   1.048,   1.047,   1.046,   1.045,
  140.   1.044,   1.043,   1.042,   1.041,   1.040,   1.039,   1.038,   1.038,
  141.   1.037,   1.036,   1.035,   1.034,   1.033,   1.033,   1.032,   1.031,
  142.   1.030,   1.029,   1.029,   1.028,   1.027,   1.026,   1.026,   1.025,
  143.   1.024,   1.024,   1.023,   1.022,   1.022,   1.021,   1.020,   1.020,
  144.   1.019,   1.018,   1.018,   1.017,   1.017,   1.016,   1.015,   1.015,
  145.   1.014,   1.014,   1.013,   1.013,   1.012,   1.012,   1.011,   1.011,
  146.   1.010,   1.010,   1.010,   1.009,   1.009,   1.008,   1.008,   1.008,
  147.   1.007,   1.007,   1.006,   1.006,   1.006,   1.005,   1.005,   1.005,
  148.   1.005,   1.004,   1.004,   1.004,   1.003,   1.003,   1.003,   1.003,
  149.   1.002,   1.002,   1.002,   1.002,   1.002,   1.002,   1.001,   1.001,
  150.   1.001,   1.001,   1.001,   1.001,   1.001,   1.000,   1.000,   1.000,
  151.   1.000,   1.000,   1.000,   1.000,   1.000,   1.000,   1.000,   1.000 }; 
  152.   
  153. /* end cosec array, 512 items long (for Sints 001 to 512) */
  154.  
  155.  
  156. float  LR_learn_default(max_wts)
  157. int  max_wts;
  158. /*
  159. ----------------------------------------------------------------------
  160.   Given a layer's maximum number of incoming weights, this routine will
  161.    calculate a "good" first cut at a learning rate for use as a default
  162.    when prompting the user.
  163.    
  164.   The constants used in this routine are entirely heuristic in nature.
  165.    The 15.0 (for "learn") comes from the formula for delta weight. 
  166.    Note:
  167.    
  168.      dW = learn_rate * delta * output
  169.      
  170.    for "typical" delta and output values (specifically, delta=.125 at
  171.    output=.5), a dW of 1.0 arises from a learning rate of 16 (I picked
  172.    15 to yield slightly more conservative learning rates). Dividing
  173.    this by the number of weights tells how much the learning rate 
  174.    should be.
  175. ----------------------------------------------------------------------
  176. */
  177. BEGIN
  178.    float  temp;
  179.  
  180.    temp = 15.0 / (float)max_wts;
  181.    return( ((temp > 2.5) ? 2.5 : temp) );
  182.  
  183. END /* LR_learn_default */
  184.  
  185.  
  186. float  LR_momentum_default(max_wts)
  187. int  max_wts;
  188. /*
  189. ----------------------------------------------------------------------
  190.   Given some maximum number of incoming weights, this routine will
  191.    calculate a "good" first cuts at a momentum value for use as default
  192.    when prompting the user.
  193.    
  194.   The constants used in this routine are entirely heuristic in nature.
  195.    The momentum scale is my own makeshift linear relation between momentum
  196.    and max number of weights. It assumes that a momentum of 1.0 corresponds
  197.    to 0 max_wts, and a momentum of 0.0 corresponds to 2250 max_wts.
  198. ----------------------------------------------------------------------
  199. */
  200. BEGIN
  201.    float  temp;
  202.  
  203.    if (max_wts > 2250)
  204.       temp = 0.1;
  205.    else
  206.       temp = 1.0 - (0.0004 * (float)max_wts);
  207.    
  208.    return( ((temp > 0.9) ? 0.9 : temp) );
  209.  
  210. END /* LR_momentum_default */
  211.  
  212.  
  213. float  LR_scale_default(learn)
  214. float  learn;
  215. /*
  216. ----------------------------------------------------------------------
  217.   Given a layer's maximum number of incoming weights and base learning
  218.    rate, this routine will calculate a "good" first cut at a scaling 
  219.    factor for use as a default when prompting the user.
  220.    
  221.   The constants used in this routine are entirely heuristic in nature.
  222.    The 2.5 and 30.836 for the scale come from two different places.
  223.    First, the 2.5 is the learning rate needed to get a minimum dW 
  224.    (.001 for NETS) at the minimum output (.2) and the minimum error 
  225.    (.01 which yields a delta of .002). The formula in LR_learn_default
  226.    is used to calculate a min learning rate of 2.5 with these values. 
  227.    Then, the Don Woods function for calculating a new learning rate:
  228.    
  229.       learn = SCALE * cosecant(err) + MIN_LEARN_RATE - SCALE
  230.    
  231.    can be worked backwords to solve for scale. The result is the formula
  232.    for the "scale" variable with the cosecant(.01) - 1.0 = 30.836
  233. ----------------------------------------------------------------------
  234. */
  235. BEGIN
  236.    return( (2.5 - learn) / 30.836 );
  237.  
  238. END /* LR_scale_default */
  239.  
  240.  
  241. float  LR_learn_from_scale(scale)
  242. float  scale;
  243. /*
  244. ----------------------------------------------------------------------
  245.   This routine is the exact opposite from the LR_scale_default and
  246.   gives the learning rate from scale information.
  247. ----------------------------------------------------------------------
  248. */
  249. BEGIN
  250.    return( 2.5 - (30.836 * scale) );
  251.  
  252. END /* LR_learn_from_scale */
  253.  
  254.  
  255. D_Sint  LR_calc_learn_rate(learn_base, learn_scale, avg_err)
  256. float  learn_base, learn_scale;
  257. Sint   avg_err;
  258. /*
  259. ----------------------------------------------------------------------
  260.   Given the average error for one (or more) IO pairs, this routine 
  261.   returns a learning rate according to the function:
  262.   
  263.        scale * cosecant(error * pi) + (base - scale);
  264.        
  265.   To get the appropriate value from the table, one need only access the
  266.   cosec array using the Sint avg_err value. Note that since the cosecant
  267.   function is symetric about pi/2, I have only stored the cosecant 
  268.   values for .001 to .5; thus if the incoming error is greater than 
  269.   512 (which is SINT_SCALE / 2), then simply subtract it from SINT_SCALE
  270.   and then reference the cosec array.
  271.  NOTE THAT VALUES IN COSEC ARRAY are stored at indicies STARTING WITH 0.
  272.   Thus, you must subtract 1 from the incoming avg_err parameter in order
  273.   to reference the correct place in the cosec array. 
  274.      ... however ...
  275.   Note also that some errors reported by avg_err can be 0. This would
  276.   correspond to an infinity value for the cosecant function. Thus, rather
  277.   than subtract 1 from the avg_err, it is simply left alone. As a result,
  278.   every reference to cosec is automatically made at +1 to the avg_err.
  279. ----------------------------------------------------------------------
  280. */
  281. BEGIN
  282. #if  USE_SCALED_INTS
  283.    static int  max_csc = SINT_SCALE / 2;
  284.    float       csc;
  285.    
  286.    /*-------------------------------------------*/
  287.    /* if the error is greater than .5, subtract */
  288.    /* from 1 (as a Sint) and then consult cosec */
  289.    /*-------------------------------------------*/
  290.    if (avg_err > max_csc)
  291.       csc = cosec[SINT_SCALE - avg_err];
  292.    else
  293.       csc = cosec[avg_err];
  294.       
  295.    return((D_Sint) 
  296.           C_float_to_Sint(learn_scale * csc + learn_base - learn_scale));
  297. #else
  298.    if ((avg_err <= 0) || (avg_err >= 1.0))
  299.       return((D_Sint)learn_base);
  300.    else
  301.       return((D_Sint)
  302.              ((learn_scale * 1.0 / sin(PI * avg_err)) + learn_base - learn_scale) );
  303. #endif
  304.  
  305. END /* LR_calc_learn_rate */
  306.